/*
 * debugMonitor.c
 *
 *  Created on: Feb 4, 2012
 *      Author: Craig Markham
 *		Class:  TCSS 371
 *		Assignment:
 */

#include "debugMonitor.h"

/*
 * DebugMonitor - Loads, runs and debugs SC2 files
 */

int mainMenu() {
    printf("\n\n1) Load, 2) Run, 3) Set BreakPoint, 4)Step, 5) Show mem, "
    		"6) Show reg, 0) Exit\n::");
    int opt;
    scanf("%d", &opt);
    return opt;
}

/*
 * open a file containing a loadable program and read that text
 * into main memory starting at the load address given in the first line
 * of the file (use the same format as the LC-3 load file)
 */
void loadProgram(CPU * CPU_ptr){
	char filename[2000], temp[2];
	// i is location in input file, j is location in scan hex value;
	// k is main memory location
	int i = 0, j = 0, k = 0, error = 0;
	ushort byte;

	FILE* fp;
    long file_size;
    char* program;
    size_t program_size, char_count;

    printf("Enter filename (or path) of program to load: ");
	scanf("%s", filename);

	if ((fp = fopen(filename, "r")) == NULL){
		printf("error Read File could not be opened \n");
	}

    fseek(fp, 0, SEEK_END);
    file_size = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    program_size = sizeof(char) * file_size;
    program = malloc(program_size);
    char_count = fread(program, 1, file_size, fp); // This should be the same as file_size
    fclose(fp);

    //Load beginning memory address. Gets first four chars
	char hex[] = {program[0], program[1], program[2], program[3]};
	sscanf(hex, "%x", &base);

   	//Loads each chars into a ushort memory space
    for (i = 4; i < (char_count - 1);) {

    	for(j = 0; j < 2;){
    		if ((program[i] > 47) && (program[i] < 123)){
				temp[j] = program[i];
				i++;
				j++;
			} else {
				i++;

			}
    	}
         sscanf(temp, "%2X", &byte);
         memory_storeByteTo(CPU_ptr->mainMemory, base + k, byte);
         k++;
    }
	CPU_ptr->PC = base;
}

/*
 * sets cpu_ptr->PC to 0x3000, start of user program; sets debugState to RUN
 */
void runProgram(CPU * CPU_ptr){
	CPU_ptr->PC = base;
	CPU_ptr->debugState = RUN;

	cpu_run(CPU_ptr);
}

/*
 * sets cpu->PC to 0x3000, sets debugState to STEP
 */
void stepProgram(CPU * CPU_ptr){
	CPU_ptr->debugState = STEP;
	cpu_run(CPU_ptr);
	showMemory(CPU_ptr, CPU_ptr->PC);
	showRegisters(CPU_ptr);
}

/*
 * refreshes register contents; returns to cpu_run()
 */
void showRegisters(CPU * CPU_ptr){
	int i, error = 0;
	printf("\nReg#     Value");
	for(i = 0; i < REGISTER_COUNT; i++){
	printf("\n$R%02d        0x%x", i,
			registerFile_getRegValue(CPU_ptr->registerFile, i, &error));
	}
	printf("\n\nSW      0x%04X            Branch Flags", CPU_ptr->SW);
	printf("\nPC      0x%04X              n:%d", CPU_ptr->PC, CPU_ptr->alu_ptr->negative_flag);
	printf("\nIR      0x%04X              z:%d", CPU_ptr->IR, CPU_ptr->alu_ptr->zero_flag);
	printf("\nMDR     0x%04X              p:%d", CPU_ptr->MDR, CPU_ptr->alu_ptr->positive_flag);
	printf("\nMAR     0x%04X", CPU_ptr->MAR);
}

/*
 * gets start address to dump and shows 16 words of memory in following format:
 *  address	byte  byte
 *  x3400    2A    01
 *            ^     ^
 *            |     +-- byte at x3401
 *            +-------- byte at x3400
 */
void showMemory(CPU * CPU_ptr, int address){
	int i, error;
	printf("\nMemory Module\naddress byte  byte\n");
	for (i = address; i < address + 32; i++) {
		printf("0x%04X     ", i);
		printf("0x%02X     ", memory_fetchByteFrom(CPU_ptr->mainMemory, i, &error));
		printf("0x%02X\n", memory_fetchByteFrom(CPU_ptr->mainMemory, ++i, &error));
	}
}

/*
 * refreshes all screen variables
 */
void showAll(CPU * CPU_ptr){
	int i, error = 0;

	for(i = 0; i < 12; i++){
		printf("\n");
	}

	printf("\nSC2 Debug Monitor");
	printf("\nJames Marquardt and Craig Markham\n");

	printf("\nRegister File                       Memory Module \n");

	printf("\nReg#    Value                 Address     Byte    Byte");
	for(i = 0; i < REGISTER_COUNT; i++){
	printf("\n$R%02d    0x%04X                0x%04X      %02X      %02X",
			i, registerFile_getRegValue(CPU_ptr->registerFile, i, &error),
			(i * 2) + CPU_ptr->PC, memory_fetchByteFrom(CPU_ptr->mainMemory, (i * 2) + CPU_ptr->PC, &error),
			memory_fetchByteFrom(CPU_ptr->mainMemory, (i * 2) + CPU_ptr->PC + 1, &error));
	}


	printf("\n\nSW      0x%04X            Branch Flags", CPU_ptr->SW);
	printf("\nPC      0x%04X              n:%d", CPU_ptr->PC, CPU_ptr->alu_ptr->negative_flag);
	printf("\nIR      0x%04X              z:%d", CPU_ptr->IR, CPU_ptr->alu_ptr->zero_flag);
	printf("\nMDR     0x%04X              p:%d", CPU_ptr->MDR, CPU_ptr->alu_ptr->positive_flag);
	printf("\nMAR     0x%04X", CPU_ptr->MAR);
}

/*
 * Not implemented in this phase
 */
void setBreakpoint(CPU * CPU_ptr){}


